package com.pangu.web.view;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.View;

public abstract class AbstractView implements View {
	protected final Log log = Logs.getLog(getClass());

	public static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8";
	public static final String MODEL_ATTRIBUTE_NAME = "obj";

	private String modelAttributeName = MODEL_ATTRIBUTE_NAME;

	private String contentType = DEFAULT_CONTENT_TYPE;

	private final Map<String, Object> staticAttributes = new HashMap<String, Object>();

	public void setAttributes(Map<String, Object> attributes) {
		if (attributes != null)
			this.staticAttributes.putAll(attributes);
	}

	public Map<String, Object> getAttributes() {
		return this.staticAttributes;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public String getContentType() {
		return this.contentType;
	}

	public void setModelAttributeName(String modelAttributeName) {
		this.modelAttributeName = Strings.isBlank(modelAttributeName) ? MODEL_ATTRIBUTE_NAME
				: modelAttributeName;
	}

	public String getModelAttributeName() {
		return this.modelAttributeName;
	}

	public void render(HttpServletRequest request,
			HttpServletResponse response, Object model) throws Throwable {
		if (log.isDebugEnabled()) {
			log.debug("Rendering view with model " + model
					+ " and static attributes " + this.staticAttributes);
		}

		Map<String, Object> mergedModel;
		if (model == null) {
			mergedModel = new HashMap<String, Object>(
					this.staticAttributes.size());
			mergedModel.putAll(this.staticAttributes);
		} else {
			if (model instanceof Map) {
				@SuppressWarnings("unchecked")
				Map<String, Object> modelMap = (Map<String, Object>) model;
				mergedModel = new HashMap<String, Object>(
						this.staticAttributes.size() + modelMap.size());
				mergedModel.putAll(this.staticAttributes);
				mergedModel.putAll(modelMap);
			} else {
				mergedModel = new HashMap<String, Object>(
						this.staticAttributes.size() + 1);
				mergedModel.putAll(this.staticAttributes);
				mergedModel.put(getModelAttributeName(), model);
			}
		}

		prepareResponse(request, response);
		renderMergedOutputModel(mergedModel, request, response);
	}

	/**
	 * set other response header if you want
	 * @param request
	 * @param response
	 */
	protected void prepareResponse(HttpServletRequest request,
			HttpServletResponse response) {
		response.setContentType(getContentType());
	}

	protected abstract void renderMergedOutputModel(Map<String, Object> map,
			HttpServletRequest request, HttpServletResponse response) throws Throwable;
}
